package com.cn.bulu.utils.finishShadeUtils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


/**
 * 成品帘价格计算工具类
 * @author wyw
 *
 */
public class FinishShadePriceUtils {
	
	/**
	 * 输入的宽和高, 高高于所有门幅的
	 * 输入一定数量的宽和高(高是高于所有门幅的),得到合适的门幅和高的集合
	 * @param doors  门幅集合
	 * @param finishs FinishShadePrice的集合, 这是输入一共的宽和高
	 * @return FinishShadePrice的集合,里面只有doorWidh需要用的门幅, 和high需要用的宽度
	 */
	public static List<FinishShadePrice> getDosageOfFinishShade(List<Double> doors,List<FinishShadePrice> finishs){
		//最开始的排序
		Collections.sort(doors);
		Collections.sort(finishs,new Comparator<FinishShadePrice>(){
			public int compare(FinishShadePrice o1, FinishShadePrice o2) {
				int i=o2.getHigh().compareTo(o1.getHigh());
				if (i==0) {
					int j=o2.getWide().compareTo(o1.getWide());
					return j;
				}
				return i;
			}
		});
		List<FinishShadePrice> listResult=new ArrayList<FinishShadePrice>();
		for(int i=0;i<finishs.size();i++){
			//整理出能用的门幅
			List<Double> doors2=new ArrayList<Double>();
			for(Double door:doors){
				if (door>=finishs.get(i).getWide()) {
					doors2.add(door);   
				}
			}
			//遍历可以用的门幅, 算出每一个可以用的门幅对应的用不量
			//一个集合装所有门幅的面积和他本身在循环里面消掉了几个宽和高
			List<Double> list=new ArrayList<Double>();
 			for(int j=0;j<doors2.size();j++){
				//用第一个门幅来跑宽和高的第一个                                                                                                                                                                        
				Double poor=doors2.get(j)-finishs.get(i).getWide();
				//这是统计这个方法里面被调了,消去多少个下级
				int count=1;
				//这里写一个一个门幅可以得到的所有面 这个方法就是用一个门幅放弃的面积 和移除了原来finishs中宽和高的个数
				FinishShadePrice finishShadePrice=FinishShadePriceUtils.calculatePrice(poor, finishs,i,count);
				//说明可以和下面pin
				Double areaAve=finishShadePrice.getGiveUpArea()/(finishShadePrice.getCount());
				list.add(areaAve);
			} 
 			//这也是需求合适的门幅,是另外的两种方式
 			List<Double> list2=new ArrayList<Double>();
 			for(int j=0;j<doors2.size();j++){
 				Double poor=doors2.get(j)-finishs.get(i).getWide();
 				int count=1;
 				//这里写一个方法,得到放弃的面积和移除了原来finishs中宽和高的个数
 				FinishShadePrice finishShadePrice=null;
					//来一个包装集合
				List<FinishShadePrice> packageList=new ArrayList<FinishShadePrice>();
				packageList.addAll(finishs);
 				finishShadePrice=FinishShadePriceUtils.calculatePriceTWO(poor,packageList,i,count);
 				Double areaAve=finishShadePrice.getGiveUpArea()/(finishShadePrice.getCount());
 				list2.add(areaAve);
 			}
 			//list中的最小值
 			//list去重
 			for(int a=0;a<list.size();a++){
 				for(int b=0;b<list.size();b++){
 					if (list.get(a)==list.get(b)) {
						if (a>b) {
							list.set(a, 100.0);
						}else if(a<b){
							list.set(a, 100.0);	
						}
					}
 				}
 			}
 			for(int a=0;a<list2.size();a++){
 				for(int b=0;b<list2.size();b++){
 					if (list.get(a)==list2.get(b)) {
						if (a>b) {
							list2.set(a, 100.0);
						}else if(a<b){
							list2.set(b,100.0);
						}
					}
 				}
 			}
 			Double listmin=Collections.min(list);

 			Double listmin2=Collections.min(list2);
 			//list2中的最小值
 			FinishShadePrice finishShadePrice=new FinishShadePrice();
 			if (listmin2>=listmin) {
					Integer aInteger= list.indexOf(listmin);
		 			Double doorResult = doors2.get(aInteger);
					Double poor=doorResult-finishs.get(i).getWide();
					finishShadePrice.setDoorWidth(doorResult);
					finishShadePrice.setHigh(finishs.get(i).getHigh());
					List<FinishShadePriceMini> listResultMini=new ArrayList<FinishShadePriceMini>();
					List<FinishShadePriceMini> listMini = FinishShadePriceUtils.calculatePriceOfReallRemove(poor, finishs, i,listResultMini);
					finishShadePrice.setListMini(listMini);
					listResult.add(finishShadePrice);
 			}else{
 					//得到合适的门幅
 					Double doorResult=doors2.get(list2.indexOf(listmin2));
 					Double poor=doorResult-finishs.get(i).getWide();
 					finishShadePrice.setDoorWidth(doorResult);
 					finishShadePrice.setHigh(finishs.get(i).getHigh());
 					List<FinishShadePriceMini> listResultMini=new ArrayList<FinishShadePriceMini>();

 					
 					FinishShadePriceUtils.calculatePriceTWORemove(poor, finishs, i,listResultMini);
 					finishShadePrice.setListMini(listResultMini);
 					listResult.add(finishShadePrice);
 				   
			}
 			
 			
 			//得到list中最小的值,他的序列号(合适门幅的序号)
 			//Integer aInteger=list.indexOf(Collections.min(list));
 			//得到这个合适的门幅(这个意思是用已经用这个门幅)


		}
		
		return listResult;
	}
	/**
	 * 移除
	 * @param poor
	 * @param finishs
	 * @param i
	 * @param count
	 */
	public static List<FinishShadePriceMini> calculatePriceTWORemove(Double poor, List<FinishShadePrice> finishs, int i,List<FinishShadePriceMini> mini){
		//剩余面积
		//Double area=poor*finishs.get(i).getHigh();
		//判断剩下可以用的宽, 然后排序
		List<FinishShadePrice> list=new ArrayList<FinishShadePrice>();
		for(int j=i+1;j<finishs.size();j++){
			if (poor>=finishs.get(j).getWide()) {
				//这就说明这个的宽可以用
				FinishShadePrice finishShadePrice=new FinishShadePrice();
				finishShadePrice.setWide(finishs.get(j).getWide());
				finishShadePrice.setHigh(finishs.get(j).getHigh());
				finishShadePrice.setIndex(j);
				list.add(finishShadePrice);
			}
		}
		if (list.size()>0) {
			Collections.sort(list,new Comparator<FinishShadePrice>() {
				public int compare(FinishShadePrice o1, FinishShadePrice o2) {
					int a=o2.getHigh().compareTo(o1.getHigh());
					if (a==0) {
						return o2.getWide().compareTo(o1.getWide());
					}
					return a;
				}	
			});
			//这说明还要递归
			Double poor2=poor-list.get(0).getWide();
			FinishShadePriceMini finishShadePriceMini=new FinishShadePriceMini();
			finishShadePriceMini.setWide(finishs.get(list.get(0).getIndex()).getWide());
			finishShadePriceMini.setHigh(finishs.get(list.get(0).getIndex()).getHigh());
			mini.add(finishShadePriceMini);
			finishs.remove(list.get(0).getIndex());
			if (i<finishs.size()-1) {
				FinishShadePriceUtils.calculatePriceTWORemove(poor2, finishs, i, mini);
			}
			return mini;
		}else{
			//这就不需要递归了,把剩余面积以及

			return mini;
		}

	}
	/**
	 * 不比较面积,按高的高低算一个宽和高丢掉的布和消去的次数
	 * @param poor 门幅减去第一个宽和高的剩余值
	 * @param finishs 宽和高的集合
	 * @param i  宽和高的集合序列
	 * @param count 一共消去下面宽和高的个数
	 * @return  放弃的面积和消去宽和高的个数
	 */
	private static FinishShadePrice calculatePriceTWO(Double poor, List<FinishShadePrice> finishs, int i, int count) {
		//剩余面积
		Double high=finishs.get(i).getHigh();
		Double area=poor*high;
		//判断剩下可以用的宽, 然后排序
		List<FinishShadePrice> list=new ArrayList<FinishShadePrice>();
		for(int j=i+1;j<finishs.size();j++){
			if (poor>=finishs.get(j).getWide()) {
				//这就说明这个的宽可以用
				FinishShadePrice finishShadePrice=new FinishShadePrice();
				finishShadePrice.setWide(finishs.get(j).getWide());
				finishShadePrice.setHigh(finishs.get(j).getHigh());
				finishShadePrice.setIndex(j);
				list.add(finishShadePrice);
			}
		}
		if (list.size()>0) {
			Collections.sort(list,new Comparator<FinishShadePrice>() {
				public int compare(FinishShadePrice o1, FinishShadePrice o2) {
					int a=o2.getHigh().compareTo(o1.getHigh());
					if (a==0) {
						return o2.getWide().compareTo(o1.getWide());						
					}
					return a;
				}	
			});
			//这说明还要递归
			count++;
			Double poor2=poor-list.get(0).getWide();
			FinishShadePrice fin=null;
			finishs.remove(list.get(0).getIndex());  
			if (i<finishs.size()-1) {
				fin = FinishShadePriceUtils.calculatePriceTWO(poor2, finishs, i, count);
			}
			return fin;
		}else{
			//这就不需要递归了,把剩余面积以及
			FinishShadePrice finishShadePrice=new FinishShadePrice();
			finishShadePrice.setGiveUpArea(area);
			finishShadePrice.setCount(count);
			return finishShadePrice;
		}
		
		
	}

	/**
	 * 用一个合适的门幅消去宽和高集合的所有相关的值
	 * @param poor 一个合适门幅减去宽的剩余值
	 * @param finishs 装载很多宽和高的集合   里面的关键字是widt,high
	 * @param i 这是宽和高集合的序号
	 */
	public static List<FinishShadePriceMini> calculatePriceOfReallRemove(Double poor,List<FinishShadePrice> finishs,int i,List<FinishShadePriceMini> mini){
		//剩余值
		Double area=poor*finishs.get(i).getHigh();
		//存放areaPoor
		List<FinishShadePrice> list=new ArrayList<FinishShadePrice>();
		for(int j=i+1;j<finishs.size();j++){
			if (poor>=finishs.get(j).getWide()) {
				Double areaFinishs=(finishs.get(j).getHigh())*(finishs.get(j).getWide());
				Double areaPoor=area-areaFinishs;
				//存的第一位是差,第二位是他的序列号
				if (areaPoor>=0) {
					FinishShadePrice finishShadePrice=new FinishShadePrice();
					finishShadePrice.setArea(areaPoor);
					finishShadePrice.setIndex(j);
					list.add(finishShadePrice);
				}
			}

		}

		//这就取得了最适合的最适合的宽和高的index
		if (list.size()==0||list==null) {
			
			return mini;
		}else {
			//给area排序
			Collections.sort(list,new Comparator<FinishShadePrice>(){
				public int compare(FinishShadePrice o1, FinishShadePrice o2) {
					return o1.getArea().compareTo(o2.getArea());
				}
			});
			Double poor2=poor-finishs.get(list.get(0).getIndex()).getWide();                                                                                                                          
			if(i<finishs.size()-1){
				FinishShadePriceMini finishShadePriceMini2=new FinishShadePriceMini();
				finishShadePriceMini2.setHigh(finishs.get(i).getHigh());
				finishShadePriceMini2.setWide(finishs.get(i).getWide());
				mini.add(finishShadePriceMini2);
				
				FinishShadePriceMini finishShadePriceMini=new FinishShadePriceMini();
				finishShadePriceMini.setWide(finishs.get(list.get(0).getIndex()).getWide());
				finishShadePriceMini.setHigh(finishs.get(list.get(0).getIndex()).getHigh());
				mini.add(finishShadePriceMini);
				FinishShadePriceUtils.calculatePriceOfReallRemove(poor2, finishs,i,mini);
				//移除(根据finishs中的序列号移除的)
				finishs.remove(list.get(0).getIndex());         
			}	
			return mini;
		}
	}
	
	
	/**
	 * 得到一个合适的门幅
	 * @param poor 门幅减去上一个宽得到的剩余值
	 * @param finishs 最开始的那个宽和高的集合
	 * @param i finish的序列号
	 * @return FinishShadePrice giveUpArea放弃的面积    count消去下面可以利用的布的次数
	 */
	public static FinishShadePrice calculatePrice(Double poor,List<FinishShadePrice> finishs,int i,int count) {	
		//剩余值
		Double area=poor*finishs.get(i).getHigh();
		//存放areaPoor
		List<FinishShadePrice> list=new ArrayList<FinishShadePrice>();
		for(int j=i+1;j<finishs.size();j++){
			if (poor>=finishs.get(j).getWide()){
				Double areaFinishs=(finishs.get(j).getHigh())*(finishs.get(j).getWide());
				Double areaPoor=area-areaFinishs;
				//存的第一位是差,第二位是他的序列号
				if (areaPoor>=0) {
					FinishShadePrice finishShadePrice=new FinishShadePrice();
					finishShadePrice.setArea(areaPoor);
					finishShadePrice.setIndex(j);
					list.add(finishShadePrice);
				}
			}

		}

		
		//这就取得了最适合的最适合的宽和高的index
		if (list.size()==0||list==null) {
			//说明poor不可以用了, 这个时候poor就需要抛弃了,这个是抛弃的面积
			FinishShadePrice finishShadePrice=new FinishShadePrice();
			finishShadePrice.setGiveUpArea(area);
			finishShadePrice.setCount(count);
			return finishShadePrice;
		}else {
			//给area排序
			Collections.sort(list,new Comparator<FinishShadePrice>(){
				public int compare(FinishShadePrice o1, FinishShadePrice o2) {
					return o1.getArea().compareTo(o2.getArea());
				}
			});
			Double poor2=poor-finishs.get(list.get(0).getIndex()).getWide();
			FinishShadePrice calculatePrice=null;
			if(i<finishs.size()-1){
				count++;
				calculatePrice = FinishShadePriceUtils.calculatePrice(poor2, finishs,i,count);
			}	
			return calculatePrice;
		}

		
		
	}
	//这是计算所有高低于最高门幅的
	//那么问题来了,这个方法的返回值就返回实际的宽,和定高布的高
	
	public static List<FinishShadePrice> getDosageOfFinishBelowDoor (List<Double> doors,List<FinishShadePrice> finishs){
		Collections.sort(doors);
		Collections.sort(finishs,new Comparator<FinishShadePrice>(){
			public int compare(FinishShadePrice o1, FinishShadePrice o2) {
				int i=o2.getHigh().compareTo(o1.getHigh());
				if (i==0) {
					int j=o2.getWide().compareTo(o1.getWide());
					return j;
				}
				return i;
			}
		});
		List<FinishShadePrice> list=new ArrayList<FinishShadePrice>();
		//门幅都当成定高布,所有宽就按实际的宽,高就按门幅
		for(int i=0;i<finishs.size();i++){
			      
			//在门幅中选择一个最适合的门幅(就是这个门幅大于等于高, 并且离高是最近的)
			List<Double> doors2=new ArrayList<Double>();
			for(int j=0;j<doors.size();j++){
				if (doors.get(j)>=finishs.get(i).getHigh()) {
					doors2.add(doors.get(j));
				}
			}
			Collections.sort(doors2,new Comparator<Double>() {
				public int compare(Double o1, Double o2){
					return o1.compareTo(o2);
				}
			});
			//第一个门幅就是最合适的
			FinishShadePrice finishShadePrice=new FinishShadePrice();
			finishShadePrice.setWide(finishs.get(i).getWide());
			finishShadePrice.setDoorWidth(doors2.get(0));
			list.add(finishShadePrice);
		}
		return list;
		
	}
	
	
	
	
	
	
	
	
	public static void main(String[] args) {

		FinishShadePrice finishsDoor1=new FinishShadePrice();
		finishsDoor1.setWide(0.69);
		finishsDoor1.setHigh(3.5);
		FinishShadePrice finishsDoor7=new FinishShadePrice();
		finishsDoor7.setWide(0.65);
		finishsDoor7.setHigh(3.5);
		FinishShadePrice finishsDoor2=new FinishShadePrice();
		finishsDoor2.setWide(0.88);
		finishsDoor2.setHigh(3.4);
		FinishShadePrice finishsDoor4=new FinishShadePrice();
		finishsDoor4.setWide(1.9);
		finishsDoor4.setHigh(3.2);		
		FinishShadePrice finishsDoor3=new FinishShadePrice();
		finishsDoor3.setWide(1.2);
		finishsDoor3.setHigh(3.3);
		FinishShadePrice finishsDoor5=new FinishShadePrice();
		finishsDoor5.setWide(1.6);
		finishsDoor5.setHigh(3.1);
		FinishShadePrice finishsDoor6=new FinishShadePrice();
		finishsDoor6.setWide(0.9);
		finishsDoor6.setHigh(3.1);


		List<Double> doors=new ArrayList<Double>();
		doors.add(2.0);
		doors.add(2.3);        
		
		List<FinishShadePrice> finishs=new ArrayList<FinishShadePrice>();
		finishs.add(finishsDoor1);
		finishs.add(finishsDoor2);
		finishs.add(finishsDoor3);
		finishs.add(finishsDoor4);
		finishs.add(finishsDoor5);
		finishs.add(finishsDoor6);
		finishs.add(finishsDoor7);

		//这是原有面积
		Double area2=0.0;
		for(FinishShadePrice finishShadePrice:finishs){
			if (finishShadePrice.getWide()!=null&&finishShadePrice.getHigh()!=null) {	
				area2+=finishShadePrice.getWide()*finishShadePrice.getHigh();
			}
		}
		System.out.println("原有的面积=="+area2);
		List<FinishShadePrice> dosageOfFinishShade = FinishShadePriceUtils.getDosageOfFinishShade(doors, finishs);
		Double area=0.0;
		for(FinishShadePrice finishShadePrice:dosageOfFinishShade){
			System.out.println(finishShadePrice.getDoorWidth()+"--"+finishShadePrice.getHigh());
			System.out.println("-----他们消去的宽和高如下--------");
			for(FinishShadePriceMini finishShadePriceMini:finishShadePrice.getListMini()){
				System.out.println(finishShadePriceMini.getWide()+"--"+finishShadePriceMini.getHigh());
			}
			System.out.println("--------------");
			if (finishShadePrice.getDoorWidth()!=null&&finishShadePrice.getHigh()!=null) {
				area=area+(finishShadePrice.getDoorWidth())*(finishShadePrice.getHigh());
			}
			
		}

		System.out.println("计算后的面积=="+area);
	
		System.out.println("浪费的布的面积=="+(area-area2));
		System.out.println("我这是看看-----------------------");

		double   f   =  98231.5585456;  
		DecimalFormat    df   = new DecimalFormat("0.000");  
		
		System.out.println(df.format(f));
	}
	
	
}
